# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1305.9.5 -> 1.1305.9.6 # drivers/char/agp/hp-agp.c 1.25 -> 1.26 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/06/14 vojtech@kernel.bkbits.net 1.1305.10.6 # Merge # -------------------------------------------- # 03/06/17 davidm@tiger.hpl.hp.com 1.1305.9.6 # Make hp-agp.c compile again. It's still broken, because the generic # AGP code once again thinks all AGP bridges must be PCI devices. # -------------------------------------------- # diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c --- a/drivers/char/agp/hp-agp.c Thu Jun 19 00:45:43 2003 +++ b/drivers/char/agp/hp-agp.c Thu Jun 19 00:45:43 2003 @@ -1,17 +1,36 @@ /* - * HP AGPGART routines. + * HP AGPGART routines. + * Copyright (C) 2002-2003 Hewlett-Packard Co + * Bjorn Helgaas */ +#include #include #include #include #include + +#include + #include "agp.h" #ifndef log2 #define log2(x) ffz(~(x)) #endif +#define HP_ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */ + +/* HP ZX1 IOC registers */ +#define HP_ZX1_IBASE 0x300 +#define HP_ZX1_IMASK 0x308 +#define HP_ZX1_PCOM 0x310 +#define HP_ZX1_TCNFG 0x318 +#define HP_ZX1_PDIR_BASE 0x320 + +/* HP ZX1 LBA registers */ +#define HP_ZX1_AGP_STATUS 0x64 +#define HP_ZX1_AGP_COMMAND 0x68 + #define HP_ZX1_IOVA_BASE GB(1UL) #define HP_ZX1_IOVA_SIZE GB(1UL) #define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2) @@ -20,6 +39,9 @@ #define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL #define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> hp_private.io_tlb_shift) +/* AGP bridge need not be PCI device, but DRM thinks it is. */ +static struct pci_dev fake_bridge_dev; + static struct aper_size_info_fixed hp_zx1_sizes[] = { {0, 0, 0}, /* filled in by hp_zx1_fetch_size() */ @@ -31,8 +53,8 @@ }; static struct _hp_private { - struct pci_dev *ioc; - volatile u8 *registers; + volatile u8 *ioc_regs; + volatile u8 *lba_regs; u64 *io_pdir; // PDIR for entire IOVA u64 *gatt; // PDIR just for GART (subset of above) u64 gatt_entries; @@ -59,7 +81,7 @@ * - IOVA space is 1Gb in size * - first 512Mb is IOMMU, second 512Mb is GART */ - hp->io_tlb_ps = INREG64(hp->registers, HP_ZX1_TCNFG); + hp->io_tlb_ps = INREG64(hp->ioc_regs, HP_ZX1_TCNFG); switch (hp->io_tlb_ps) { case 0: hp->io_tlb_shift = 12; break; case 1: hp->io_tlb_shift = 13; break; @@ -75,13 +97,13 @@ hp->io_page_size = 1 << hp->io_tlb_shift; hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; - hp->iova_base = INREG64(hp->registers, HP_ZX1_IBASE) & ~0x1; + hp->iova_base = INREG64(hp->ioc_regs, HP_ZX1_IBASE) & ~0x1; hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE; hp->gart_size = HP_ZX1_GART_SIZE; hp->gatt_entries = hp->gart_size / hp->io_page_size; - hp->io_pdir = phys_to_virt(INREG64(hp->registers, HP_ZX1_PDIR_BASE)); + hp->io_pdir = phys_to_virt(INREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE)); hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { @@ -95,7 +117,8 @@ return 0; } -static int __init hp_zx1_ioc_owner(u8 ioc_rev) +static int __init +hp_zx1_ioc_owner (void) { struct _hp_private *hp = &hp_private; @@ -130,47 +153,28 @@ return 0; } -static int __init hp_zx1_ioc_init(void) +static int __init +hp_zx1_ioc_init (u64 ioc_hpa, u64 lba_hpa) { struct _hp_private *hp = &hp_private; - struct pci_dev *ioc; - int i; - u8 ioc_rev; - - ioc = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_IOC, NULL); - if (!ioc) { - printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no IOC\n"); - return -ENODEV; - } - hp->ioc = ioc; - - pci_read_config_byte(ioc, PCI_REVISION_ID, &ioc_rev); - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (pci_resource_flags(ioc, i) == IORESOURCE_MEM) { - hp->registers = (u8 *) ioremap(pci_resource_start(ioc, i), - pci_resource_len(ioc, i)); - break; - } - } - if (!hp->registers) { - printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no CSRs\n"); - return -ENODEV; - } + hp->ioc_regs = ioremap(ioc_hpa, 1024); + hp->lba_regs = ioremap(lba_hpa, 256); /* * If the IOTLB is currently disabled, we can take it over. * Otherwise, we have to share with sba_iommu. */ - hp->io_pdir_owner = (INREG64(hp->registers, HP_ZX1_IBASE) & 0x1) == 0; + hp->io_pdir_owner = (INREG64(hp->ioc_regs, HP_ZX1_IBASE) & 0x1) == 0; if (hp->io_pdir_owner) - return hp_zx1_ioc_owner(ioc_rev); + return hp_zx1_ioc_owner(); return hp_zx1_ioc_shared(); } -static int hp_zx1_fetch_size(void) +static int +hp_zx1_fetch_size(void) { int size; @@ -180,47 +184,53 @@ return size; } -static int hp_zx1_configure(void) +static int +hp_zx1_configure (void) { struct _hp_private *hp = &hp_private; agp_bridge->gart_bus_addr = hp->gart_base; +#if 0 + /* ouch!! can't do that with a non-PCI AGP bridge... */ agp_bridge->capndx = pci_find_capability(agp_bridge->dev, PCI_CAP_ID_AGP); - pci_read_config_dword(agp_bridge->dev, - agp_bridge->capndx + PCI_AGP_STATUS, &agp_bridge->mode); +#else + agp_bridge->capndx = 0; +#endif + agp_bridge->mode = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS); if (hp->io_pdir_owner) { - OUTREG64(hp->registers, HP_ZX1_PDIR_BASE, - virt_to_phys(hp->io_pdir)); - OUTREG64(hp->registers, HP_ZX1_TCNFG, hp->io_tlb_ps); - OUTREG64(hp->registers, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1)); - OUTREG64(hp->registers, HP_ZX1_IBASE, hp->iova_base | 0x1); - OUTREG64(hp->registers, HP_ZX1_PCOM, - hp->iova_base | log2(HP_ZX1_IOVA_SIZE)); - INREG64(hp->registers, HP_ZX1_PCOM); + OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_phys(hp->io_pdir)); + OUTREG64(hp->ioc_regs, HP_ZX1_TCNFG, hp->io_tlb_ps); + OUTREG64(hp->ioc_regs, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1)); + OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, hp->iova_base | 0x1); + OUTREG64(hp->ioc_regs, HP_ZX1_PCOM, hp->iova_base | log2(HP_ZX1_IOVA_SIZE)); + INREG64(hp->ioc_regs, HP_ZX1_PCOM); } return 0; } -static void hp_zx1_cleanup(void) +static void +hp_zx1_cleanup (void) { struct _hp_private *hp = &hp_private; if (hp->io_pdir_owner) - OUTREG64(hp->registers, HP_ZX1_IBASE, 0); - iounmap((void *) hp->registers); + OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0); + iounmap((void *) hp->ioc_regs); } -static void hp_zx1_tlbflush(struct agp_memory *mem) +static void +hp_zx1_tlbflush (struct agp_memory *mem) { struct _hp_private *hp = &hp_private; - OUTREG64(hp->registers, HP_ZX1_PCOM, hp->gart_base | log2(hp->gart_size)); - INREG64(hp->registers, HP_ZX1_PCOM); + OUTREG64(hp->ioc_regs, HP_ZX1_PCOM, hp->gart_base | log2(hp->gart_size)); + INREG64(hp->ioc_regs, HP_ZX1_PCOM); } -static int hp_zx1_create_gatt_table(void) +static int +hp_zx1_create_gatt_table (void) { struct _hp_private *hp = &hp_private; int i; @@ -247,7 +257,8 @@ return 0; } -static int hp_zx1_free_gatt_table(void) +static int +hp_zx1_free_gatt_table (void) { struct _hp_private *hp = &hp_private; @@ -259,8 +270,8 @@ return 0; } -static int hp_zx1_insert_memory(struct agp_memory *mem, off_t pg_start, - int type) +static int +hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type) { struct _hp_private *hp = &hp_private; int i, k; @@ -305,8 +316,8 @@ return 0; } -static int hp_zx1_remove_memory(struct agp_memory *mem, off_t pg_start, - int type) +static int +hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type) { struct _hp_private *hp = &hp_private; int i, io_pg_start, io_pg_count; @@ -325,11 +336,28 @@ return 0; } -static unsigned long hp_zx1_mask_memory(unsigned long addr, int type) +static unsigned long +hp_zx1_mask_memory (unsigned long addr, int type) { return HP_ZX1_PDIR_VALID_BIT | addr; } +static void +hp_zx1_enable (u32 mode) +{ + struct _hp_private *hp = &hp_private; + u32 command; + + command = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS); + + command = agp_collect_device_status(mode, command); + command |= 0x00000100; + + OUTREG32(hp->lba_regs, HP_ZX1_AGP_COMMAND, command); + + agp_device_command(command, 0); +} + struct agp_bridge_driver hp_zx1_driver = { .owner = THIS_MODULE, .size_type = FIXED_APER_SIZE, @@ -339,7 +367,7 @@ .tlb_flush = hp_zx1_tlbflush, .mask_memory = hp_zx1_mask_memory, .masks = hp_zx1_masks, - .agp_enable = agp_generic_enable, + .agp_enable = hp_zx1_enable, .cache_flush = global_cache_flush, .create_gatt_table = hp_zx1_create_gatt_table, .free_gatt_table = hp_zx1_free_gatt_table, @@ -352,71 +380,93 @@ .cant_use_aperture = 1, }; -static int __init agp_hp_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init +hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa) { struct agp_bridge_data *bridge; int error; - /* ZX1 LBAs can be either PCI or AGP bridges */ - if (!pci_find_capability(pdev, PCI_CAP_ID_AGP)) - return -ENODEV; - - printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n", - pdev->slot_name); + printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset (ioc=%lx, lba=%lx)\n", ioc_hpa, lba_hpa); - error = hp_zx1_ioc_init(); + error = hp_zx1_ioc_init(ioc_hpa, lba_hpa); if (error) return error; bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; - bridge->driver = &hp_zx1_driver; - bridge->dev = pdev; - pci_set_drvdata(pdev, bridge); + fake_bridge_dev.vendor = PCI_VENDOR_ID_HP; + fake_bridge_dev.device = PCI_DEVICE_ID_HP_ZX1_LBA; + bridge->dev = &fake_bridge_dev; + return agp_add_bridge(bridge); } -static void __devexit agp_hp_remove(struct pci_dev *pdev) +static acpi_status __init +zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) { - struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - - agp_remove_bridge(bridge); - agp_put_bridge(bridge); -} - -static struct pci_device_id agp_hp_pci_table[] __initdata = { - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_HP, - .device = PCI_DEVICE_ID_HP_ZX1_LBA, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { } -}; + acpi_handle handle, parent; + acpi_status status; + struct acpi_buffer buffer; + struct acpi_device_info *info; + u64 lba_hpa, sba_hpa, length; + int match; + + status = hp_acpi_csr_space(obj, &lba_hpa, &length); + if (ACPI_FAILURE(status)) + return 1; + + /* Look for an enclosing IOC scope and find its CSR space */ + handle = obj; + do { + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(handle, &buffer); + if (ACPI_SUCCESS(status)) { + /* TBD check _CID also */ + info = buffer.pointer; + info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0'; + match = (strcmp(info->hardware_id.value, "HWP0001") == 0); + ACPI_MEM_FREE(info); + if (match) { + status = hp_acpi_csr_space(handle, &sba_hpa, &length); + if (ACPI_SUCCESS(status)) + break; + else { + printk(KERN_ERR PFX "Detected HP ZX1 " + "AGP LBA but no IOC.\n"); + return status; + } + } + } -MODULE_DEVICE_TABLE(pci, agp_hp_pci_table); + status = acpi_get_parent(handle, &parent); + handle = parent; + } while (ACPI_SUCCESS(status)); -static struct pci_driver agp_hp_pci_driver = { - .name = "agpgart-hp", - .id_table = agp_hp_pci_table, - .probe = agp_hp_probe, - .remove = agp_hp_remove, -}; + if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) + return 1; + return 0; +} -static int __init agp_hp_init(void) +static int __init +agp_hp_init (void) { - return pci_module_init(&agp_hp_pci_driver); + acpi_status status; + + status = acpi_get_devices("HWP0003", zx1_gart_probe, "HWP0003 AGP LBA", NULL); + if (!(ACPI_SUCCESS(status))) { + agp_bridge->type = NOT_SUPPORTED; + printk(KERN_INFO PFX "Failed to initialize zx1 AGP.\n"); + return -ENODEV; + } + return 0; } -static void __exit agp_hp_cleanup(void) +static void __exit +agp_hp_cleanup (void) { - pci_unregister_driver(&agp_hp_pci_driver); } module_init(agp_hp_init);